#include <stdlib.h>
#include "basicblock.h"

instruction_t* create_instruction(bool isStatic,uint address)
{
	instruction_t *newInstr = (instruction_t*)malloc(sizeof(instruction_t));
	newInstr->instr = NULL;
	newInstr->next = NULL;
	newInstr->prev = NULL;
	newInstr->address = 0;
	return newInstr;
}

instruction_list_t* create_instruction_list()
{
	instruction_list_t *newList = (instruction_list_t*)malloc(sizeof(instruction_list_t));
	newList->first = NULL;
	newList->last = NULL;
	return newList;
}

void instruction_list_append(instruction_list_t *list, instruction_t *instr)
{
	if(instr==NULL||list==NULL)
		return;
	if(list->first==NULL){
		list->first = instr;
		list->last = instr;
		instr->prev = NULL;
		instr->next = NULL;
		return;
	}
	instr->prev = list->last;
	instr->next = NULL;
	list->last->next = instr;
	list->last = instr;
}

basicblock_t* create_basicblock()
{
	basicblock_t *newBB = (basicblock_t*)malloc(sizeof(basicblock_t));

	if(newBB == NULL){
		return NULL;
	}

	newBB->id = -1;
	newBB->first_address = 0;
	newBB->last_address = 0;
	newBB->last_length = 0;
	newBB->branch_kind = NODEFINE;
	newBB->next_branch = NULL;
	newBB->next_unbranch = NULL;
	newBB->isStatic = false;
	//newBB->instrlist_dynamic = NULL;
	//newBB->instrlist_static = NULL;
	newBB->bb_instr_list = NULL;
	return newBB;
}

basicblock_t* create_basicblock(uint first_addr,uint last_addr)
{
	basicblock_t *newBB = (basicblock_t*)malloc(sizeof(basicblock_t));

	if(newBB == NULL){
		return NULL;
	}

	newBB->id = -1;
	newBB->first_address = first_addr;
	newBB->last_address = last_addr;
	newBB->last_length = 0;
	newBB->branch_kind = NODEFINE;
	newBB->next_branch = NULL;
	newBB->next_unbranch = NULL;
	newBB->isStatic = false;
	//newBB->instrlist_dynamic = NULL;
	//newBB->instrlist_static = NULL;
	newBB->bb_instr_list = NULL;
	return newBB;
}

void delete_basicblock(basicblock_t *bb)
{
	if(bb == NULL){
		return;
	}

	delete bb;
	bb = NULL;
}

basicblock_t* split_basicblock(basicblock_t *ori,uint splitAddress)
{
	if(ori==NULL){
		return NULL;
	}
	if(splitAddress > ori->last_address
		|| splitAddress < ori->first_address){
		return NULL;
	}

	basicblock_t *secondBB = create_basicblock();

	if(secondBB==NULL)
		return NULL;

	//ori->last_address = splitAddress-1;

	secondBB->first_address = splitAddress;
	secondBB->last_address = ori->last_address;
	secondBB->isStatic = ori->isStatic;
	
	////////// Spilt the instruction list /////////////
	if(ori->isStatic||!ori->isStatic){
		instruction_list_t *oriList = create_instruction_list();
		instruction_list_t *secondList = create_instruction_list();
		instruction_t *current = ori->bb_instr_list->first;
		while(current!=NULL){
			if(current->address>=splitAddress){
				ori->last_address = current->prev->address;
				break;
			}
			instruction_list_append(oriList,current);
			if(current == ori->bb_instr_list->last){
				ori->last_address = current->address;
				break;
			}
			current = current->next;		
		}
		
		while(current!=NULL){
			instruction_list_append(secondList,current);
			if(current == ori->bb_instr_list->last){
				break;
			}
			current = current->next;
		}
		ori->bb_instr_list = oriList;
		secondBB->bb_instr_list = secondList;
	}else{
		/*instrlist_t *oriList = (instrlist_t*)malloc(sizeof(instrlist_t*));
		instrlist_t *secondList = (instrlist_t*)malloc(sizeof(instrlist_t*));
		instrlist_set_translation_target(oriList,(app_pc)splitAddress);
		instrlist_set_translation_target(secondList,instrlist_get_translation_target(ori->instrlist_dynamic));
		for(instr_t *current=instrlist_first(ori->instrlist_dynamic);current!=NULL;current=instr_get_next(current))
		{
			if((uint)instr_get_app_pc(current)>=splitAddress){
				instrlist_append(secondList,current);
			}else{
				instrlist_append(oriList,current);
			}
		}
		ori->instrlist_dynamic = oriList;
		secondBB->instrlist_dynamic = secondList;*/
	}

	/* Do not delete the original BB here*/
	return secondBB;
}

